/**
 * 
 */
package t4j.generics;

import java.util.List;

interface SuperPower {
}

interface XRayVision extends SuperPower {
	void seeThroughWalls();
}

interface SuperHearing extends SuperPower {
	void hearSubtleNoises();
}

interface SuperSmell extends SuperPower {
	void trackBySmell();
}

class SuperHero<POWER extends SuperPower> {
	POWER power;

	public SuperHero(POWER power) {
		this.power = power;
	}

	POWER getPower() {
		return power;
	}
}

// 因为POWER extends SuperPower的子接口，所以可以成功继承SuperHero，
// 同时把泛型参数传给父类POWER，父类的power域的类型就是这里的POWER
class SuperSleuth<POWER extends XRayVision> extends SuperHero<POWER> {

	public SuperSleuth(POWER power) {
		super(power);
	}

	void see() {
		power.seeThroughWalls();
	}// 这里可以调用父类的power域，并且类型是这里的POWER
}

class CanineHero<POWER extends SuperHearing & SuperSmell> extends SuperHero<POWER> {

	public CanineHero(POWER power) {
		super(power);
	}

	void hear() {
		power.hearSubtleNoises();
	}

	void smell() {
		power.trackBySmell();
	}
}

class SuperHearSmell implements SuperHearing, SuperSmell {

	@Override
	public void trackBySmell() { System.out.println("SuperHearSmell.trackBySmell()");
	}

	@Override
	public void hearSubtleNoises() {
		 System.out.println("SuperHearSmell.hearSubtleNoises()");
	}

}

class XRayVisionImp implements XRayVision{

	@Override
	public void seeThroughWalls() {System.out.println("XRayVisionImp");}
	
}

class DogBoy extends CanineHero<SuperHearSmell> {

	public DogBoy() {
		super(new SuperHearSmell());
	}
}

class CatBoy extends SuperSleuth<XRayVisionImp>{

	public CatBoy() {
	
		super(new XRayVisionImp());
	}
}

public class EpicBattle {

	static <POWER extends SuperHearing> void useSuperHearing(SuperHero<POWER> hero) {
		hero.getPower().hearSubtleNoises();
	}

	static <POWER extends SuperHearing & SuperSmell> void superFind(SuperHero<POWER> hero) {
		hero.getPower().hearSubtleNoises();
		hero.getPower().trackBySmell();

	}
	
	static <POWER extends XRayVision> void catBoy(SuperHero<POWER> hero){
		hero.getPower().seeThroughWalls();
	}

	public static void main(String[] args) {
		DogBoy dogBoy = new DogBoy();

		useSuperHearing(dogBoy);

		superFind(dogBoy);

		catBoy(new CatBoy());
		
		//you can do this
		List<? extends SuperHearing> audioBoys;
		//but you can't do this:
		//List<? extends SuperHearing & SuperSmell> dogBoys;
	}
}
